import { RepoLink, Link, Warning } from '@brillout/docpress'
import { UiFrameworkExtension } from '../../components'

Environment: client.

The `navigate('/some/url')` function enables you to programmatically switch pages. In other words, you can implement navigations that aren't triggered by the user clicking on an anchor link `<a>`.

For example, you can use `navigate()` to redirect the user after a successful form submission:

```jsx
import { navigate } from 'vike/client/router'

function Form() {
   return (
     <form onSubmit={onSubmit}>
       {/* ... */}
     </form>
   )
}

async function onSubmit() {
  const navigationPromise = navigate('/form/success')
  console.log("The URL changed but the new page hasn't rendered yet.")
  await navigationPromise
  console.log('The new page has finished rendering.')
}
```

> If you want to redirect the user while rendering a page (e.g. redirect non-authenticated users to a login page), then use <Link href='/redirect'>`throw redirect()`</Link> instead. See <Link href="/abort#throw-redirect-vs-throw-render-vs-navigate" doNotInferSectionTitle={true} />.

> If you want to navigate back, then use [`window.history.back()`](https://developer.mozilla.org/en-US/docs/Web/API/History/back) instead.


## Options

 - `navigate('/some-url', { keepScrollPosition: true })`: Don't scroll to the top of the page, preserve the scroll position instead. See also <Link href="/clientRouting#settings">`<a href="/some-url" keep-scroll-position />`</Link>.
 - `navigate('/some-url', { overwriteLastHistoryEntry: true })`: Don't create a new entry in the browser's history, instead let the new URL replace the current URL. (This effectively removes the current URL from the browser history).


## `history.pushState()`

If you want to change the URL completely independently of Vike then use [`history.pushState()`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState) instead of `navigate()`.

Make sure you implement your navigation handling by listening to the [`popstate` event](https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event).

<Warning>You need to handle the `popstate` event yourself, otherwise you'll break the browser's back- and forward history button.</Warning>

```js
window.addEventListener('popstate', (event) => {
  // Vike sets triggeredBy to 'vike' | 'browser' | 'user'
  const { triggeredBy } = window.history.state
  /* Equivalent:
  const { triggeredBy } = event.state
  */

  // Navigation triggered by Vike or the browser
  if (triggeredBy === 'vike' || triggeredBy === 'browser') {
    // Abort: let Vike handle the navigation
    return
  }

  // Navigation triggered by your history.pushState() call
  if (triggeredBy === 'user') {
    // Implement your navigation handling here
  }
})
```


## Without `vike-{react,vue,solid}`

If you don't use a <UiFrameworkExtension /> and if you use <Link text="Server Routing" href="/server-routing" /> then use `window.location.href = '/some/url'` instead of `navigate()` (because `navigate()` requires <Link text="Client Routing" href="/client-routing" />).

> The <UiFrameworkExtension plural noLink /> use Client Routing.


## See also

- <Link href="/redirect" />
- <Link href="/redirects" />
- <Link href="/abort#throw-redirect-vs-throw-render-vs-navigate" doNotInferSectionTitle={true} />
